using System;
using System.Collections.Generic;
using Firestarter.DB_DomainModel.Logic;
using Firestarter.DB_DomainModel.Logic.Test.DBChangesImporterTests;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using FireStarterModeller.Test;
using FireStarterModeller.Test.BO;
using Habanero.BO;
using NUnit.Framework;
using Rhino.Mocks;

namespace Firestarter.DB_DomainModel.Logic.Test
{
    [TestFixture]
    public class TestDBToDMRelationshipImporter : TestBase
    {

        [Test]
        public void Test_Construct()
        {
            //---------------Set up test pack-------------------
            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dbToDMRelationshipImporter);
            Assert.AreSame(relationshipNameGenerator, dbToDMRelationshipImporter.RelationshipNameGenerator);
        }

        [Test]
        public void Test_Construct_WhenNullRelationshipNameGenerator_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                new DBToDMRelationshipImporter(null);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("relationshipNameGenerator", ex.ParamName);
            }
        }

        [Test]
        public void Test_Import_WhenDBForeignKeyIsNull_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                IList<string> errorMessages;
                dbToDMRelationshipImporter.Import(null, out errorMessages);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dbForeignKey", ex.ParamName);
            }
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenNoColumns_ShouldClearExistingDMRelationshipProperties()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            IDMClass ownerClass = dmRelationship.OwnerClass;

            dbForeignKey.ForeignKeyColumns[0].MarkForDelete();

            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedDMRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------

            Assert.IsNull(returnedDMRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("A relationship could not be created for the foreign key " + 
                "called '{0}' on table '{1}' since it does not have any columns", 
                dbForeignKey.ForeignKeyName, dbForeignKey.ParentTable);
            StringAssert.Contains(expectedMessage, message);

            //Assert.AreEqual(0, dbToDMRelationshipImporter.ErrorMessages.Count);
            //Assert.IsNotNull(returnedDMRelationship);
            //Assert.AreSame(dmRelationship, returnedDMRelationship);
            //Assert.AreEqual(0, dmRelationship.RelationshipProperties.Count);
            //Assert.AreSame(returnedDMRelationship.MappedDBForeignKey, dbForeignKey);
        }

        

        private static DBForeignKey CreateForeignKeyWithMappedRelationshipWithOneRelatedProp()
        {
            DBDatabase database = new DBDatabase();
            string relatedTableName = TestUtilsShared.GetRandomString();
            DBTable relatedTable = new DBTable(relatedTableName).ApproveForAdd();
            database.Tables.Add(relatedTable);
            string ownerTableName = TestUtilsShared.GetRandomString();
            DBTable ownerTable = new DBTable(ownerTableName).ApproveForAdd();
            database.Tables.Add(ownerTable);

            DBTableBuilder relatedTableBuilder = new DBTableBuilder(relatedTable);
            relatedTableBuilder.AddPrimaryKeyColumn().ApproveForAdd();

            DBTableBuilder ownerTableBuilder = new DBTableBuilder(ownerTable);
            DBForeignKey foreignKey = ownerTableBuilder.AddForeignKey(TestUtilsShared.GetRandomString(), relatedTable).ApproveForAdd();
            foreignKey.ForeignKeyColumns[0].ApproveForAdd().ParentColumn.ApproveForAdd();

            DMSolution solution = TestUtilsDMSolution.CreateUnsavedValidDMSolution();
            IDBTypeToDMPropertyTypeMapper dbTypeToDMPropertyTypeMapper = MockRepository.GenerateStub<IDBTypeToDMPropertyTypeMapper>();
            dbTypeToDMPropertyTypeMapper.Stub(t => t.GetDMPropertyType(null)).IgnoreArguments().Return(new DMPropertyType());
            IDBChangesImporter importer = new DBToDMImporterFactory(dbTypeToDMPropertyTypeMapper, new RelationshipNameGenerator()).CreateDBChangesImporter();
            importer.ImportDBChanges(database, solution);

            return foreignKey;
        }

        private static DBForeignKey CreateUpdatedForeignKeyWithMappedRelationship()
        {
            DBForeignKey foreignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DBTable parentTable = foreignKey.ParentTable;
            DMClass parentClass = parentTable.MappedDMClass;

            DBColumn newFKColumn = new DBColumn("NewFKColumn");
            parentTable.Columns.Add(newFKColumn);
            DMProperty newFKProperty = new DMProperty { MappedDBColumn = newFKColumn };
            parentClass.Properties.Add(newFKProperty);

            foreignKey.ForeignKeyColumns[0].ParentColumn = newFKColumn;

            return foreignKey;
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenChangedParentColumn_ShouldUpdateRelationshipProperty()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            DMClass ownerClass = (DMClass) dmRelationship.OwnerClass;
            DMClass relatedClass = (DMClass) dmRelationship.RelatedClass;

            DBColumn newParentColumn = new DBColumn("NewFKColumn");
            newParentColumn.Table = dbForeignKey.ParentTable;
            DMProperty newParentProperty = new DMProperty { PropertyName = "NewFKProperty" };
            newParentProperty.MappedDBColumn = newParentColumn;
            newParentProperty.Class = ownerClass;

            dbForeignKey.ForeignKeyColumns[0].ParentColumn = newParentColumn;

            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmRelationship);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.IsNotNull(dmRelationship.RelatedClass);
            Assert.AreNotSame(newParentProperty, dmRelationship.RelationshipProperties[0].OwnerProperty);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedRelationship);
            Assert.AreSame(dmRelationship, ownerClass.OwnerRelationships[0]);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.AreSame(newParentProperty, dmRelationship.RelationshipProperties[0].OwnerProperty);

            Assert.IsTrue(dmRelationship.Status.IsValid(), "Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.Status.IsValidMessage);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenChangedRelatedColumn_ShouldUpdateRelationshipProperty()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            DMClass ownerClass = (DMClass) dmRelationship.OwnerClass;
            DMClass relatedClass = (DMClass) dmRelationship.RelatedClass;

            DBColumn newRelatedColumn = new DBColumn("NewRelatedColumn");
            newRelatedColumn.Table = dbForeignKey.RelatedTable;
            DMProperty newRelatedProperty = new DMProperty { PropertyName = "NewRelatedProperty" };
            newRelatedProperty.MappedDBColumn = newRelatedColumn;
            newRelatedProperty.Class = relatedClass;

            dbForeignKey.ForeignKeyColumns[0].RelatedColumn = newRelatedColumn;

            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmRelationship);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.IsNotNull(dmRelationship.RelatedClass);
            Assert.AreNotSame(newRelatedProperty, dmRelationship.RelationshipProperties[0].RelatedProperty);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedRelationship);
            Assert.AreSame(dmRelationship, ownerClass.OwnerRelationships[0]);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.AreSame(newRelatedProperty, dmRelationship.RelationshipProperties[0].RelatedProperty);

            Assert.IsTrue(dmRelationship.Status.IsValid(), "Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.Status.IsValidMessage);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenChangedBothRelatedAndParentColumns_ShouldUpdateRelationshipProperty()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            DMClass ownerClass = (DMClass) dmRelationship.OwnerClass;
            DMClass relatedClass = (DMClass) dmRelationship.RelatedClass;

            DBColumn newRelatedColumn = new DBColumn("NewRelatedColumn");
            newRelatedColumn.Table = dbForeignKey.RelatedTable;
            DMProperty newRelatedProperty = new DMProperty { PropertyName = "NewRelatedProperty" };
            newRelatedProperty.MappedDBColumn = newRelatedColumn;
            newRelatedProperty.Class = relatedClass;

            DBColumn newParentColumn = new DBColumn("NewFKColumn");
            newParentColumn.Table = dbForeignKey.ParentTable;
            DMProperty newParentProperty = new DMProperty { PropertyName = "NewFKProperty" };
            newParentProperty.MappedDBColumn = newParentColumn;
            newParentProperty.Class = ownerClass;

            dbForeignKey.ForeignKeyColumns[0].ParentColumn = newParentColumn;
            dbForeignKey.ForeignKeyColumns[0].RelatedColumn = newRelatedColumn;

            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmRelationship);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.IsNotNull(dmRelationship.RelatedClass);
            Assert.AreNotSame(newRelatedProperty, dmRelationship.RelationshipProperties[0].RelatedProperty);
            Assert.AreNotSame(newParentProperty, dmRelationship.RelationshipProperties[0].OwnerProperty);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedRelationship);
            Assert.AreSame(dmRelationship, ownerClass.OwnerRelationships[0]);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            Assert.AreSame(newRelatedProperty, dmRelationship.RelationshipProperties[0].RelatedProperty);
            Assert.AreSame(newParentProperty, dmRelationship.RelationshipProperties[0].OwnerProperty);

            Assert.IsTrue(dmRelationship.Status.IsValid(), "Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.Status.IsValidMessage);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_NoColumns()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            IDMClass dmClass = dbColumn.MappedDMProperty.Class;
            DBTable dbTable = dmClass.MappedTable;

            DBForeignKey dbForeignKey = new DBForeignKey { ForeignKeyName = "ForeignKeyName", ParentTable = dbTable };

            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreSame(dbTable, dmClass.MappedTable);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("A relationship could not be created for the foreign key called '{0}' on table '{1}' since it does not have any columns", 
                dbForeignKey.ForeignKeyName, dbForeignKey.ParentTable);
            StringAssert.Contains(expectedMessage, message);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_OneColumns()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DMClass dmClass = (DMClass) dbColumn.MappedDMProperty.Class;
            DBTable dbTable = dmClass.MappedTable;

            DBColumn relatedDBColumn = CreateColumnWithMappedProp("Related Table", "relatedDBColumn");
            IDMClass relatedClass = relatedDBColumn.MappedDMProperty.Class;

            DBForeignKey dbForeignKey = new DBForeignKey { ForeignKeyName = "ForeignKeyName", 
                ParentTable = dbTable, RelatedTable = relatedDBColumn.Table };
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            Assert.AreEqual(dmClass.MappedTableID, dbTable.TableID);
            Assert.IsNotNull(dmClass.MappedTable, "The class should be mapped to a table");
            Assert.AreSame(dbTable, dmClass.MappedTable);
            Assert.AreSame(dbColumn.ColumnName, dmClass.Properties[0].MappedDBColumnName);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmRelationship);
            Assert.AreSame(dmClass, dmRelationship.OwnerClass);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            DMProperty expectedBoProp = dmClass.Properties[0];
            IDMProperty actualBoProp = dmRelationship.RelationshipProperties[0].OwnerProperty;
            Assert.IsNotNull(actualBoProp);
            Assert.AreSame(expectedBoProp, actualBoProp);

            Assert.IsNotNull(dmRelationship.RelatedClass);
            Assert.AreSame(relatedClass, dmRelationship.RelatedClass);
            Assert.AreSame(relatedClass.Properties[0], dmRelationship.RelationshipProperties[0].RelatedProperty);

            Assert.IsTrue(dmRelationship.Status.IsValid(), "Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.Status.IsValidMessage);
            Assert.IsTrue(dmRelationship.ReverseRelationship.Status.IsValid(), "Reverse Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.ReverseRelationship.Status.IsValidMessage);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_OneColumns_NoRelatedClass()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DMClass dmClass = (DMClass) dbColumn.MappedDMProperty.Class;
            DBTable dbTable = dmClass.MappedTable;

            DBTable relatedTable = new DBTable("Related Table");
            DBColumn relatedDBColumn = new DBColumn("relatedDBColumn");
            relatedTable.Columns.Add(relatedDBColumn);

            DBForeignKey dbForeignKey = new DBForeignKey {ForeignKeyName = "ForeignKeyName", 
                ParentTable = dbTable, RelatedTable = relatedTable};
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            Assert.AreEqual(dmClass.MappedTableID, dbTable.TableID);
            Assert.IsNotNull(dmClass.MappedTable, "The class should be mapped to a table");
            Assert.AreSame(dbTable, dmClass.MappedTable);
            Assert.AreSame(dbColumn.ColumnName, dmClass.Properties[0].MappedDBColumnName);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("since the related table '{0}' for column '{1}' is not mapped to a domain model class",
                 relatedTable.TableNameDB, relatedDBColumn.ColumnName);
            StringAssert.Contains(expectedMessage, message);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_OneColumns_NoRelatedColumn()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = new DBForeignKey {ForeignKeyName = "ForeignKeyName"};

            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DMClass dmClass = (DMClass) dbColumn.MappedDMProperty.Class;
            DBTable dbTable = dmClass.MappedTable;

//            DBTable relatedTable = new DBTable("Related Table");
//            DBColumn relatedDBColumn = new DBColumn("relatedDBColumn");
//            relatedTable.Columns.Add(relatedDBColumn);
//
            dbForeignKey.AddColumnInfo(dbColumn, null);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            Assert.AreEqual(dmClass.MappedTableID, dbTable.TableID);
            Assert.IsNotNull(dmClass.MappedTable, "The class should be mapped to a table");
            Assert.AreSame(dbTable, dmClass.MappedTable);
            Assert.AreSame(dbColumn.ColumnName, dmClass.Properties[0].MappedDBColumnName);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("since the column that relates to the foreign key column called '{0}' does not exist",
                 dbForeignKey.ForeignKeyColumns[0].ParentColumn.ColumnName);
            StringAssert.Contains(expectedMessage, message);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_OneColumns_NoRelatedTable()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = new DBForeignKey {ForeignKeyName = "ForeignKeyName"};
            DBColumn dbColumn;
            DBTable dbTable = CreateDBTableWithOneColumn(out dbColumn);
            DMClass dmClass = CreateBusinessObjectWithPropertyForColumn(dbTable, dbColumn);

            DBColumn relatedDBColumn = new DBColumn("relatedDBColumn");

            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            Assert.AreEqual(dmClass.MappedTableID, dbTable.TableID);
            Assert.IsNotNull(dmClass.MappedTable, "The class should be mapped to a table");
            Assert.AreSame(dbTable, dmClass.MappedTable);
            Assert.AreEqual(dbColumn.ColumnName, dmClass.Properties[0].MappedDBColumnName);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("since the table for the related column '{0}' does not exist",
                 relatedDBColumn.ColumnName);
            StringAssert.Contains(expectedMessage, message);
        }

        //        [Test]
        //        public void Test_ImportAdded_DMRelationship_ClassDoesNotExist_ShouldProduceError()
        //        {
        //            //---------------Set up test pack-------------------
        //            DBForeignKey dbForeignKey = new DBForeignKey();
        //            DBTable dbTable = GetTableInfoWithMappedBOInfo();
        //            dbForeignKey.RelatedTableID = dbTable.TableID;
        //            DBToDMRelationshipImporter boRelationshipImporter = new DBToDMRelationshipImporter
        //                (new DMSolution(TestUtils.GetRandomString()));
        //            //---------------Assert Precondition----------------
        //            Assert.AreEqual(0, dbForeignKey.ForeignKeyColumns.Count);
        //            //---------------Execute Test ----------------------
        //            DMRelationship dmRelationship = boRelationshipImporter.Import(dbForeignKey);
        //            //---------------Test Result -----------------------
        //            Assert.IsNull(dmRelationship);
        //            Assert.AreEqual(1, boRelationshipImporter.ErrorMessages.Count);
        //            string message = boRelationshipImporter.ErrorMessages[0];
        //            string expectedMessage = string.Format
        //                ("The Unique Constraint '{0}' could not be "
        //                 +
        //                 "created from the alternate key {1} since the Business Object related to the table '{2}' do not exist for the project",
        //                 dbForeignKey.ForeignKeyName, dbForeignKey.ForeignKeyName, dbTable.TableNameDB);
        //            StringAssert.Contains(expectedMessage, message);
        //        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_TwoColumns()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = new DBForeignKey();
            DBColumn dbColumn;
            DBTable dbTable = CreateDBTableWithOneColumn(out dbColumn);
            DBColumn dbColumnInfo2 = new DBColumn("Some Column1");
            dbTable.Columns.Add(dbColumnInfo2);
            DBColumn relatedDBColumn;
            DBTable relatedTable = CreateDBTableWithOneColumn(out relatedDBColumn);
            DBColumn relatedColumn2 = new DBColumn("relatedColumn2");
            relatedTable.Columns.Add(relatedColumn2);

            DMClass dmClass = CreateBusinessObjectWithPropertyForTwoColumn(dbTable, dbColumn, dbColumnInfo2);
            CreateBusinessObjectWithPropertyForTwoColumn(relatedTable, relatedDBColumn, relatedColumn2);
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);
            dbForeignKey.AddColumnInfo(dbColumnInfo2, relatedColumn2);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmRelationship);
            Assert.AreEqual(2, dmRelationship.RelationshipProperties.Count);
            DMProperty expectedBoProp = dmClass.Properties[0];
            Assert.IsTrue(dmRelationship.HasOwnerProperty(expectedBoProp));
            DMProperty expectedBoProp2 = dmClass.Properties[1];
            Assert.IsTrue(dmRelationship.HasOwnerProperty(expectedBoProp2));

            Assert.IsTrue(dmRelationship.HasRelatedProperty(relatedColumn2.MappedDMProperty));
            Assert.AreSame(dmClass, dmRelationship.OwnerClass);
            Assert.AreSame(relatedTable.MappedDMClass, dmRelationship.RelatedClass);

            Assert.IsTrue(dmRelationship.Status.IsValid(), "Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.Status.IsValidMessage);
            Assert.IsTrue(dmRelationship.ReverseRelationship.Status.IsValid(), "Reverse Relationship is not valid." +
                Environment.NewLine + "Reason: " + dmRelationship.ReverseRelationship.Status.IsValidMessage);
        }

        private static DBTable CreateDBTableWithOneColumn(out DBColumn dbColumn)
        {
            dbColumn = new DBColumn(TestUtilsShared.GetRandomString());
            DBTable dbTable = new DBTable(TestUtilsShared.GetRandomString());
            dbTable.Columns.Add(dbColumn);
            return dbTable;
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_ColumnsNotInBo()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = new DBForeignKey {ForeignKeyName = "ForeignKeyName"};
            DBColumn dbColumn = new DBColumn("Some Column");
            DBColumn dbColumnInfo2 = new DBColumn("Some Column1");
            DMClass dmClass = CreateBusinessObjectWithPropertyForTwoColumn(new DBTable(), dbColumn, dbColumnInfo2);

            DBColumn dbColumnNotInBo = new DBColumn("unmatched column");
            DBColumn relatedDBColumnNotInBo = new DBColumn("unmatched column related");
            dbForeignKey.AddColumnInfo(dbColumnNotInBo, relatedDBColumnNotInBo);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            AssertBusinessObjectContainsPropertyForColumn(dmClass, dbColumn);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationship);
            Assert.AreEqual(1, errorMessages.Count);
            string message = errorMessages[0];
            string expectedMessage = string.Format
                ("since the foreign key column '{0}' is not mapped to a domain model class property", 
                dbColumnNotInBo.ColumnName);
            StringAssert.Contains(expectedMessage, message);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_ShouldCreateAsOneToMany()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DBColumn relatedDBColumn = CreateColumnWithMappedProp("Related Table", "relatedDBColumn");

            DBForeignKey dbForeignKey = new DBForeignKey { ForeignKeyName = "ForeignKeyName" };
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = CreateDBToDMRelationshipImporter();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreEqual(Cardinality.Single, dmRelationship.Cardinality);
            Assert.AreEqual(Cardinality.Multiple, dmRelationship.ReverseRelationship.Cardinality);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_ShouldUseRelationshipNameGeneratorForRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DBColumn relatedDBColumn = CreateColumnWithMappedProp("Related Table", "relatedDBColumn");

            DBForeignKey dbForeignKey = new DBForeignKey { ForeignKeyName = "ForeignKeyName" };
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            string relationshipName = TestUtilsShared.GetRandomString();
            relationshipNameGenerator.Stub(generator => generator.CreateRelationshipName(Arg<DMRelationship>.Is.Anything)).Return(relationshipName);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            relationshipNameGenerator.AssertWasCalled(generator => generator.CreateRelationshipName(dmRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.RelationshipName);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenHasRelationshipName_ShouldNotGenerateRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            string relationshipName = dmRelationship.RelationshipName;

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationshipName);
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedDMRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedDMRelationship);
            relationshipNameGenerator.AssertWasNotCalled(generator => generator.CreateRelationshipName(dmRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.RelationshipName);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenRelationshipNameIsNull_ShouldGenerateRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            dmRelationship.RelationshipName = null;

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            string relationshipName = TestUtilsShared.GetRandomString();
            relationshipNameGenerator.Stub(generator => generator.CreateRelationshipName(Arg<DMRelationship>.Is.Anything)).Return(relationshipName);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedDMRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedDMRelationship);
            relationshipNameGenerator.AssertWasCalled(generator => generator.CreateRelationshipName(dmRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.RelationshipName);
        }

        [Test]
        public void Test_Import_WithNoExistingRelationship_ShouldUseRelationshipNameGeneratorForReverseRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = CreateColumnWithMappedProp("Some Table", "Some Column");
            DBColumn relatedDBColumn = CreateColumnWithMappedProp("Related Table", "relatedDBColumn");

            DBForeignKey dbForeignKey = new DBForeignKey { ForeignKeyName = "ForeignKeyName" };
            dbForeignKey.AddColumnInfo(dbColumn, relatedDBColumn);

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            string relationshipName = TestUtilsShared.GetRandomString();
            relationshipNameGenerator.Stub(generator => generator.CreateRelationshipName(Arg<DMRelationship>.Is.Anything)).Return(relationshipName);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship dmRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            relationshipNameGenerator.AssertWasCalled(generator => generator.CreateRelationshipName((DMRelationship) dmRelationship.ReverseRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.ReverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenHasReverseRelationshipName_ShouldNotGenerateReverseRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            string relationshipName = dmRelationship.ReverseRelationship.RelationshipName;

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationshipName);
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedDMRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedDMRelationship);
            relationshipNameGenerator.AssertWasNotCalled(generator => generator.CreateRelationshipName((DMRelationship) dmRelationship.ReverseRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.ReverseRelationship.RelationshipName);
        }

        [Test]
        public void Test_Import_WithExistingRelationship_WhenReverseRelationshipNameIsNull_ShouldGenerateReverseRelationshipName()
        {
            //---------------Set up test pack-------------------
            DBForeignKey dbForeignKey = CreateForeignKeyWithMappedRelationshipWithOneRelatedProp();
            DMRelationship dmRelationship = dbForeignKey.MappedDMRelationship;
            dmRelationship.ReverseRelationship.RelationshipName = null;

            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            string relationshipName = TestUtilsShared.GetRandomString();
            relationshipNameGenerator.Stub(generator => generator.CreateRelationshipName(Arg<DMRelationship>.Is.Anything)).Return(relationshipName);
            DBToDMRelationshipImporter dbToDMRelationshipImporter = new DBToDMRelationshipImporter(relationshipNameGenerator);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbForeignKey.ForeignKeyColumns.Count);
            Assert.AreEqual(1, dmRelationship.RelationshipProperties.Count);
            //---------------Execute Test ----------------------
            IList<string> errorMessages;
            DMRelationship returnedDMRelationship = dbToDMRelationshipImporter.Import(dbForeignKey, out errorMessages);
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, returnedDMRelationship);
            relationshipNameGenerator.AssertWasCalled(generator => generator.CreateRelationshipName((DMRelationship) dmRelationship.ReverseRelationship));
            Assert.AreEqual(relationshipName, dmRelationship.ReverseRelationship.RelationshipName);
        }

        private static DBToDMRelationshipImporter CreateDBToDMRelationshipImporter()
        {
            IRelationshipNameGenerator relationshipNameGenerator = MockRepository.GenerateStub<IRelationshipNameGenerator>();
            relationshipNameGenerator.Stub(t => t.CreateRelationshipName(null)).IgnoreArguments().Return(
                TestUtilsShared.GetRandomString());
            return new DBToDMRelationshipImporter(relationshipNameGenerator);
        }

        private DBColumn CreateColumnWithMappedProp(string tableName, string columnName)
        {
            DBColumn dbColumn = new DBColumn(columnName);
            DBTable dbTable = new DBTable(tableName);
            dbTable.Columns.Add(dbColumn);
            CreateBusinessObjectWithPropertyForColumn(dbTable, dbColumn);
            return dbColumn;
        }

        private static DMClass CreateBusinessObjectWithPropertyForColumn(DBTable dbTable, DBColumn dbColumn)
        {
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution();
            DBToDMClassImporter boImporter = new DBToDMClassImporter();
            DMClass dmClass = boImporter.Import(dmSolution, dbTable);
            IDBToDMPropertyUpdater dbToDMPropertyUpdater = MockRepository.GenerateStub<IDBToDMPropertyUpdater>();
            DBToDMPropertyImporter dbToDMPropertyImporter = new DBToDMPropertyImporter(dbToDMPropertyUpdater);
            dbToDMPropertyImporter.Import(dmClass, dbColumn);
            return dmClass;
        }

        private static DMClass CreateBusinessObjectWithPropertyForTwoColumn
            (DBTable dbTable, DBColumn dbColumn, DBColumn dbColumnInfo2)
        {
            DMClass dmClass = new DMClass { MappedTable = dbTable };
            IDBToDMPropertyUpdater dbToDMPropertyUpdater = MockRepository.GenerateStub<IDBToDMPropertyUpdater>();
            DBToDMPropertyImporter dbToDMPropertyImporter = new DBToDMPropertyImporter(dbToDMPropertyUpdater);
            dbToDMPropertyImporter.Import(dmClass, dbColumn);
            dbToDMPropertyImporter.Import(dmClass, dbColumnInfo2);
            return dmClass;
        }

        private static void AssertBusinessObjectContainsPropertyForColumn(DMClass dmClass, DBColumn info)
        {
            bool found = false;
            foreach (DMProperty propertyInfo in dmClass.Properties)
            {
                if (propertyInfo.MappedDBColumnID != info.ColumnID) continue;
                found = true;
                break;
            }
            string message = string.Format
                ("The business object property for column {0} " + "was not found for business object {1}",
                 info.ColumnName, dmClass);
            Assert.IsTrue(found, message);
        }

        private static DBTable GetTableInfoWithMappedBOInfo(out DMClass dmClass)
        {
            DBTable dbTable = new DBTable("RelatedTable");
            DMSolution dmSolution = TestUtilsDMSolution.CreateSavedDMSolution();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            return dbTable;
        }

        private static DMSolution CreateDMSolution()
        {
            DMSolution dmSolution = new DMSolution("Some DMSolution");
            DMAssembly dmAssembly = new DMAssembly(TestUtilsShared.GetRandomString());
            dmSolution.Assemblies.Add(dmAssembly);
            dmSolution.DefaultAssembly = dmAssembly;
            return dmSolution;
        }
    }
}